'''
Created on 17/gen/2012

@author: Daniel Smerghetto
'''
from PyQt4                              import QtCore,QtGui
from utils.utils                        import launchMessage
from constants.constants                import TABLE_NAME_CONFIGURATIONS
import cPickle
import logging


class MenuConfig(object):
    def __init__(self,menu_name,sequence,tooltip,parent,exe_file_path='',menu_icon_path='',children=[],type='',hide=False, primaryFlag=False, function_name='', use_configurations=False, id=False, use_browser=False, browser_sites=[], folder_path='', use_folder=False, use_cmd=False, cmd_path=''):
        super(MenuConfig,self).__init__()
        self.menu_name          =   menu_name
        self.sequence           =   sequence
        self.tooltip            =   tooltip
        self.parent             =   parent
        self.exe_file_path      =   exe_file_path
        self.menu_icon_path     =   menu_icon_path
        self.children           =   children
        self.type               =   type          # menu - action
        self.hide               =   hide
        self.primaryFlag        =   primaryFlag       # True - False
        self.function_name      =   function_name
        self.use_configurations =   use_configurations
        self.id                 =   id
        self.use_browser        =   use_browser
        self.browser_sites      =   browser_sites
        self.folder_path        =   folder_path
        self.use_folder         =   use_folder
        self.use_cmd            =   use_cmd
        self.cmd_path           =   cmd_path
        self.new                =   False
        
    def setParent(self, parent):
        if parent != None:
            self.parent = parent
            self.parent.addChild(self)
        else:
            self.parent = None
    
    def addChildren(self, children=[]):
        for child in children:
            self.addChild(child)
            
    def addChild(self, child):
        if child not in self.children:
            self.children.append(child)

    def childAtRow(self, rowIndex):
        if rowIndex > len(self.children)-1:
            return None
        return self.children[rowIndex]

    def rowOfChild(self, child):       
        for i, item in enumerate(self.children):
            if item == child:
                return i
        return -1

    def removeChildByIndex(self, row, node=None):
        if len(self.children) >= row:
            value = self.children[row]
            self.children.remove(value)
        else:
            logging.warning('Row: %s not removed from children of %s' % (row, self.menu_name))
        return True

    def removeChild(self, nodeObj):
        if nodeObj in self.children:
            self.children.remove(nodeObj)
        else:
            logging.warning('Node %s not removed' % (nodeObj.menu_name))
        return True
        
    def removeBrowserObj(self, bowserObj):
        self.browser_sites.remove(bowserObj)
        
    def addBrowserSites(self, sitesObjs=[]):
        for siteObj in sitesObjs:
            self.addBrowserSite(siteObj)
            
    def addBrowserSite(self, siteObj):
        found = False
        for siteStoredObj in self.browser_sites:
            if siteObj.name == siteStoredObj.name:
                found = True
                break
        if not found:
            self.browser_sites.append(siteObj)

    def __str__(self, *args, **kwargs):
        compString = '\n'
        compString = compString + '    Menu Name: %s '%(self.menu_name)
        #compString = compString + '    Sequence: %s '%(self.sequence)
        #compString = compString + '    Tooltip: %s '%(self.tooltip)
        if self.parent:
            compString = compString + '    Parent EL: %s '%(self.parent.menu_name)
        else:
            compString = compString + '    Parent EL: None'
        compString = compString + '    Children:[ '
        for child in self.children:
            compString = compString + '    Child: %s, '%(child.menu_name)
        compString = compString + ']'
        #compString = compString + '    Exe path: %s '%(self.exe_file_path)
        #compString = compString + '    Icon Path: %s '%(self.menu_icon_path)
        #compString = compString + '    Type: %s '%(self.type)
        compString = compString + '    Hide: %s '%(self.hide)
        return compString
    
class MenuTreeModel(QtCore.QAbstractItemModel):
    
    #refreshTableView = QtCore.pyqtSignal([])
    
    def __init__(self, children=[], headers=[], parent=False):
        self.internal = True
        if not headers:
            confObjects = parent.dbInst.getRowsTable(TABLE_NAME_CONFIGURATIONS, fields=['config_value'], filtersList=[('config_name', '=', 'MENU_CONF_HEADERS_ORDER')])
            confObjectsToHide = parent.dbInst.getRowsTable(TABLE_NAME_CONFIGURATIONS, fields=['config_value'], filtersList=[('config_name', '=', 'MENU_CONF_HEADERS_TO_HIDE')])
            allHeaders = eval(confObjects[0].config_value)
            hiddenHeaders = eval(confObjectsToHide[0].config_value)
            headers = [elem for elem in allHeaders if elem not in hiddenHeaders]
        super(MenuTreeModel,self).__init__(None)
        self.parent = parent
        self.root=MenuConfig(menu_name='ROOT',
                             sequence=0,
                             tooltip='Root Node',
                             parent=None,
                             exe_file_path='',
                             menu_icon_path='')
        self.cleanPreviousStructure()
        for child in children:
            if child in self.root.children:
                self.replaceChild(self.root, child)
            else:
                self.setChild(self.root, child)
        self.headers = headers
        self.allHeaders = allHeaders
        self.hiddenHeaders = hiddenHeaders
        colIndexes = range(len(self.allHeaders))
        self.relDict = dict(zip(colIndexes, self.allHeaders))
    
    def cleanPreviousStructure(self):
        del self.root.children[:]
        
    def replaceChild(self, parent, child):
        parent.children.remove(child)
        self.setChild(parent, child)

    def setChild(self, parent, child):
        parent.children.append(child)
        child.setParent(parent)



    @property
    def columns(self):
        return len(self.allHeaders)

    def flags(self, index):
        defaultFlags = QtCore.QAbstractItemModel.flags(self, index)     
        if index.isValid():
            #QtCore.Qt.ItemIsEditable |
            return  QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsDragEnabled | \
                    QtCore.Qt.ItemIsDropEnabled | defaultFlags  
        else:
            return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsDragEnabled | QtCore.Qt.ItemIsDropEnabled | defaultFlags

    def headerData(self, section, orientation, role):
        if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
            return QtCore.QVariant(self.allHeaders[section])
        return QtCore.QVariant()

    def insertRow(self, row, parent):
        return self.insertRows(row, 1, parent)

    def insertRows(self, row, count, parent):
        self.beginInsertRows(parent, row, (row + (count - 1)))
        self.endInsertRows()
        return True

    def removeRow(self, row, parentIndex):
        return self.removeRows(row, 1, parentIndex)

    def removeRows(self, row, count, parentIndex):
        self.beginRemoveRows(parentIndex, row, row)
        node = self.nodeFromIndex(parentIndex)
        node.removeChildByIndex(row)
        self.endRemoveRows()
        return True

    def index(self, row, column, parent=None):
        node = self.nodeFromIndex(parent)
        return self.createIndex(row, column, node.childAtRow(row))

    def getIconStatus(self, node):
        """
            return the icon status
        """
        if not node:
            return 
        iconPath = node.menu_icon_path
        if iconPath:
            return QtGui.QIcon(node.menu_icon_path)

    def data(self, index, role= QtCore.Qt.DisplayRole):
        node = self.nodeFromIndex(index)
        if role == QtCore.Qt.DecorationRole:
            if index.column() == 0:
                return self.getIconStatus(node)
        if node==None:
            return QtCore.QVariant()   
 
        if role == QtCore.Qt.TextAlignmentRole:
            return QtCore.QVariant(int(QtCore.Qt.AlignTop | QtCore.Qt.AlignLeft))

        if role != QtCore.Qt.DisplayRole:
            if role == QtCore.Qt.BackgroundRole and node.new:
                return QtGui.QBrush(QtCore.Qt.green)
            else:
                return QtCore.QVariant()

        colIndex = index.column()
        if colIndex in self.relDict:
            colName = self.relDict.get(colIndex)
            if colName in node.__dict__.keys():
                value = eval('node.' + colName)
                return QtCore.QVariant(unicode(value))
            else:
                logging.warning('colName %s not in node: %s' % (colName, node.menu_name))
            return QtCore.QVariant()
        else:                                           # if don't put else are displayed
            return QtCore.QVariant()                    # tri state in td
        

#         if index.column() == 0:
#             return QtCore.QVariant(unicode(node.menu_name))
#         elif index.column() == 1:
#             return QtCore.QVariant(unicode(node.sequence))
#         elif index.column() == 2:
#             return QtCore.QVariant(unicode(node.tooltip))
#         elif index.column() == 7:
#             return QtCore.QVariant(unicode(node.type))
#         else:                                           # if don't put else are displayed
#             return QtCore.QVariant()                    # tri state in td

    def columnCount(self,parent):
        return len(self.allHeaders)

    def rowCount(self, parent=None):
        node = self.nodeFromIndex(parent)
        if node is None:
            return 0
        return len(node.children)
    
    def parent(self, child):
        if not child.isValid():
            return QtCore.QModelIndex()

        node = self.nodeFromIndex(child)
       
        if node is None or node == False:
            return QtCore.QModelIndex()

        parent = node.parent
           
        if parent is None or parent == False:
            return QtCore.QModelIndex()
       
        grandparent = parent.parent
        if grandparent is None or grandparent == False:
            return QtCore.QModelIndex()
        row = grandparent.rowOfChild(parent)
       
        assert row != - 1
        return self.createIndex(row, 0, parent)
    
    def nodeFromIndex(self, index):
        if index:
            return index.internalPointer() if index.isValid() else self.root
        return self.root

    def supportedDropActions(self):
        if self.internal:
            return QtCore.Qt.MoveAction
        return QtCore.Qt.CopyAction
    
    def mimeTypes(self):
        return QtCore.QStringList([
                'text/uri-list',
                'application/x-qabstractitemmodeldatalist',
                'text/xml',
                ])
 
    def mimeData(self, indexes):
        mimeData = QtCore.QMimeData()
        node = self.nodeFromIndex(indexes[0])
        mimeData.setData('text/xml', cPickle.dumps(node))
        return mimeData

    def dropMimeData(self, data, action, row, column, newParentIndex):
        try:
            parentDestNode = self.nodeFromIndex(newParentIndex)
            if parentDestNode.type == 'action':
                launchMessage("You can't move an element in the lower level of an action!")
                return 
            pickleObj = data.data('text/xml')
            nodeObj = cPickle.loads(str(pickleObj))
            nodeObj.setParent(None)
            self.createIndex(row, column, nodeObj)

            if parentDestNode == self.root:
                nodeObj.primaryFlag = True
            else:
                nodeObj.primaryFlag = False
            newSeqNumber = self.parent.getAvaibleSequenceNumber(parentDestNode)
            nodeObj.setParent(parentDestNode)
            nodeObj.sequence = newSeqNumber
            self.insertRow(len(parentDestNode.children)-1, newParentIndex)
            return True
        except Exception, ex:
            launchMessage(ex)
    
class NodeComputedProxiModelSearch(QtGui.QSortFilterProxyModel ):
    def filterAcceptsRow (self, source_row, source_parent ):
        if self.filterRegExp() == "" :
            return True #Shortcut for common case
    
        if  super(NodeComputedProxiModelSearch, self).filterAcceptsRow( source_row, source_parent) :
            return True
    
        #one of our children might be accepted, so accept this row if one of our children are accepted.
        source_index = self.sourceModel().index(source_row, 0, source_parent)
        for i in range( self.sourceModel().rowCount(source_index)):
            if self.filterAcceptsRow(i, source_index):
                return True
        return False
    
    def getInnerIndex(self,qModelIndex):
        return self.mapToSource(qModelIndex)
